package orm.webservice.com;

import java.util.ArrayList;
import java.util.HashMap;

import javax.persistence.*;

import org.apache.axis.utils.StringUtils;
import org.apache.commons.logging.*;
import org.hibernate.Query;
import org.orm.PersistentException;
import org.orm.PersistentTransaction;

import orm.clinica.com.*;
import orm.clinica.com.dao.*;
import orm.clinica.com.OpcionPrestacion;
import orm.clinica.com.Paciente;
import orm.clinica.com.Prestacion;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * @author Renew21
 *	Clase que contiene los metodos que estaran disponibles en el web service.
 */
public class ClinicaWebService {
	
	
	/**
	 * Metodo que permite agregar un paciente a la base de datos por medio del web service.
	 * @param pacienteJson Recibe un json en un string con los datos que de un paciente.
	 * @return Retorna un 1 si agrego de forma correcta o un 0 si es que no fue asi.
	 */
	public int agregarPaciente(String pacienteJson){
		
		int resultado = 0;
		if(pacienteJson != null && !pacienteJson.isEmpty()){
			JsonParser jsonParser = new JsonParser();
			JsonObject paciente = jsonParser.parse(pacienteJson).getAsJsonObject();
			//Validar parametros recibidos no nulos
			System.out.println(pacienteJson);
			if(paciente.has("rut") && paciente.has("nombre") && paciente.has("direccion")){
				
				DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
				try {
					String rutV = paciente.get("rut").getAsString();
					
					//if(this.validarRut(rutV)){
					
						Paciente nuevoPaciente = new Paciente();
						nuevoPaciente.setRut(paciente.get("rut").getAsString());
						nuevoPaciente.setNombre(paciente.get("nombre").getAsString());
						nuevoPaciente.setDireccion(paciente.get("direccion").getAsString());
						lDAOFactory.getPacienteDAO().save(nuevoPaciente);
						resultado = 1;
						
					//}else{
						//return resultado;
					//}
					
				} catch (PersistentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return resultado;
	}
	
	/**
	 * Metodo que permite actualizar los datos de un paciente en la base de datos por medio del web service.
	 * @param pacienteJson Recibe un json en un string con los datos que de un paciente.
	 * @return Retorna un 1 si actualizo de forma correcta o un 0 si es que no fue asi.
	 */
	public int actualizarPaciente(String pacienteJson){
		
		int resultado = 0;
		if(pacienteJson != null && !pacienteJson.isEmpty()){
			
			JsonParser jsonParser = new JsonParser();
			JsonObject paciente = jsonParser.parse(pacienteJson).getAsJsonObject();
			
			//Validar parametros recibidos no nulos
			System.out.println(pacienteJson);
			if(paciente.has("rut") && paciente.has("nombre") && paciente.has("direccion")){
				
				PersistentTransaction t = null;
				try {
					
					t = Prueba1ClinicaPersistentManager.instance().getSession().beginTransaction();
					DAOFactory lDAOFactory = DAOFactory.getDAOFactory();

					PacienteDAO pacienteDAO = lDAOFactory.getPacienteDAO();
					Paciente upPaciente = pacienteDAO.loadPacienteByQuery("Paciente.rut = " + paciente.get("rut").getAsString(),null);
					
					if(upPaciente != null){
						upPaciente.setNombre(paciente.get("nombre").getAsString());
						upPaciente.setDireccion(paciente.get("direccion").getAsString());
						pacienteDAO.save(upPaciente);
						resultado = 1;
					}
				t.commit();
				} catch (PersistentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					
					try {
						t.rollback();
					} catch (PersistentException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}finally{
					try {
						Prueba1ClinicaPersistentManager.instance().getSession().flush();
						Prueba1ClinicaPersistentManager.instance().disposePersistentManager();
					} catch (PersistentException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		
		System.out.println(resultado);
		return resultado;
	}
	
	public int eliminarPaciente(String pacienteRut){
		int resultado = 0;
		if(pacienteRut != null){
			PersistentTransaction t = null;
			try {
				t = Prueba1ClinicaPersistentManager.instance().getSession().beginTransaction();
				DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
				Paciente paciente = lDAOFactory.getPacienteDAO().getPacienteByORMID(pacienteRut);
				lDAOFactory.getPacienteDAO().delete(paciente);
				resultado = 1;
				t.commit();
			} catch (PersistentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				try {
					t.rollback();
				} catch (PersistentException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
		return resultado;
	}
	
	
	/**
	 * Metodo que valida el rut.
	 * 
	 * @param rut
	 *            Recibe el rut antes de guion.
	 * @param dv
	 *            Recibe el digito verificardor aparte.
	 * @return Retorna true en caso de que el rut sea valido o false en caso
	 *         contrario.
	 */
	private boolean validarRut(String dato) {
		if (dato.length() > 5) {
			String digitos;
			int largo;

			digitos = dato.toUpperCase();
			largo = dato.length();

			String paso = "";

			int a = Integer.parseInt(digitos.substring(0, 1)) * 3;
			int b = Integer.parseInt(digitos.substring(1, 2)) * 2;
			int c = Integer.parseInt(digitos.substring(2, 3)) * 7;
			int p = Integer.parseInt(digitos.substring(3, 4)) * 6;
			int f = Integer.parseInt(digitos.substring(4, 5)) * 5;
			int g = Integer.parseInt(digitos.substring(5, 6)) * 4;
			int h = Integer.parseInt(digitos.substring(6, 7)) * 3;
			int i = Integer.parseInt(digitos.substring(7, 8)) * 2;
			String j = (digitos.substring(9, 10));

			int k = (a + b + c + p + f + g + h + i) % 11;
			int l = 11 - k;

			if (l != 10 || l != 11) {
				paso = digitos.substring(0, 8) + "-" + l;
			}

			if (l == 10) {
				paso = digitos.substring(0, 8) + "-" + "K";
			}

			if (l == 11) {
				paso = digitos.substring(0, 8) + "-" + "0";
			}

			if (digitos.equals(paso)) {
				return true;

			}

			else {

				return false;

			}
		} else
			return false;
	}
	
	/**
	 * Metodo que permite agregar una prestacion a la base de datos por medio del web service.
	 * @param pacienteJson Recibe un json en un string con los datos que de una prestacion que llegan dentro.
	 * @return Retorna un 1 si agrego de forma correcta o un 0 si es que no fue asi.
	 */
	public int agregarPrestacion(String prestacionJson){
		int resultado = 0;
		if(prestacionJson != null && !prestacionJson.isEmpty()){
			JsonParser jsonParser = new JsonParser();
			JsonObject prestacion = jsonParser.parse(prestacionJson).getAsJsonObject();
			//Validar parametros recibidos no nulos
			System.out.println(prestacionJson);
			if(prestacion.has("diagnostico") && prestacion.has("fecha") && prestacion.has("rutPaciente") && prestacion.has("idOpcion")){
				//Obtine Clasificacion y Genero
				DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
				try {
					Paciente paciente = lDAOFactory.getPacienteDAO().getPacienteByORMID(prestacion.get("rutPaciente").getAsString());
					OpcionPrestacion opcionPrestacion = lDAOFactory.getOpcionPrestacionDAO().getOpcionPrestacionByORMID(prestacion.get("idOpcion").getAsInt());
					if(paciente != null && opcionPrestacion != null){
						Prestacion nuevaPrestacion = new Prestacion();
						nuevaPrestacion.setDiagnostico(prestacion.get("diagnostico").getAsString());
						nuevaPrestacion.setFecha(prestacion.get("fecha").getAsString());
						nuevaPrestacion.setPacienterut(paciente);
						nuevaPrestacion.setOpcionPrestacionid_opcion(opcionPrestacion);
						lDAOFactory.getPrestacionDAO().save(nuevaPrestacion);
						resultado = 1;
					}
				} catch (PersistentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return resultado;
	}
	
	/**
	 * Metodo que permite actualizar los datos de una prestacion a la base de datos por medio del web service.
	 * @param pacienteJson Recibe un json en un string con los datos que de una prestacion.
	 * @return Retorna un 1 si actualizo de forma correcta o un 0 si es que no fue asi.
	 */
	public int actualizarPrestacion(String prestacionJson){
		int resultado = 0;
		if(prestacionJson != null && !prestacionJson.isEmpty()){
			JsonParser jsonParser = new JsonParser();
			JsonObject prestacion = jsonParser.parse(prestacionJson).getAsJsonObject();
			//Validar parametros recibidos no nulos
			System.out.println(prestacionJson);
			if(prestacion.has("idPrestacion") && prestacion.has("diagnostico") && prestacion.has("fecha") && prestacion.has("rutPaciente") && prestacion.has("idOpcion")){
				
				PersistentTransaction t = null;
				try {
					
					t = Prueba1ClinicaPersistentManager.instance().getSession().beginTransaction();
					DAOFactory lDAOFactory = DAOFactory.getDAOFactory();

					
					Paciente paciente = lDAOFactory.getPacienteDAO().getPacienteByORMID(prestacion.get("rutPaciente").getAsString());
					OpcionPrestacion opcionPrestacion = lDAOFactory.getOpcionPrestacionDAO().getOpcionPrestacionByORMID(prestacion.get("idOpcion").getAsInt());
					
					PrestacionDAO prestacionDAO = lDAOFactory.getPrestacionDAO();
					Prestacion upPrestacion = prestacionDAO.loadPrestacionByQuery("Prestacion.id_prestacion = " + prestacion.get("idPrestacion").getAsInt(),null);
					
					if(paciente != null && opcionPrestacion != null && upPrestacion != null){
						upPrestacion.setDiagnostico(prestacion.get("diagnostico").getAsString());
						upPrestacion.setFecha(prestacion.get("fecha").getAsString());
						upPrestacion.setPacienterut(paciente);
						upPrestacion.setOpcionPrestacionid_opcion(opcionPrestacion);
						lDAOFactory.getPrestacionDAO().save(upPrestacion);
						resultado = 1;
					}
					t.commit();
				} catch (PersistentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					
					try {
						t.rollback();
					} catch (PersistentException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}finally{
					try {
						Prueba1ClinicaPersistentManager.instance().getSession().flush();
						Prueba1ClinicaPersistentManager.instance().disposePersistentManager();
					} catch (PersistentException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		System.out.println(resultado);
		return resultado;
	}
	
	/**
	 * Este metodo elimina el registro de una prestacion en la base de datos.
	 * @param salaId Recibe el id de la prestacion que se quiere eliminar.
	 * @return Retorna un 1 en caso de eliminar el registro exitosamente o un 0 en caso contrario.
	 */
	public int eliminarPrestacion(int prestacionId){
		int resultado = 0;
		if(prestacionId > 0){
			PersistentTransaction t = null;
			try {
				t = Prueba1ClinicaPersistentManager.instance().getSession().beginTransaction();
				DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
				Prestacion prestacion = lDAOFactory.getPrestacionDAO().getPrestacionByORMID(prestacionId);
				lDAOFactory.getPrestacionDAO().delete(prestacion);
				resultado = 1;
				t.commit();
			} catch (PersistentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				try {
					t.rollback();
				} catch (PersistentException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
		return resultado;
	}
	/**
	 * Este metodo obtiene la totalidad de pacientes (rut, nombre y direccion) que existen en la base de datos.
	 * @return Retorna un String con formato JSON que queda a disposicion del cliente.
	 */
	public String obtenerPacientes(){
		String resultJSON = "";
		ArrayList<HashMap<String, Object>> listaPaciente = new ArrayList<HashMap<String,Object>>();
		
		DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
		System.out.println("Listing Paciente...");
		Paciente[] pacientes;
		try {
			pacientes = lDAOFactory.getPacienteDAO().listPacienteByQuery(null, null);
			int length = pacientes.length;
			System.out.println(length + " record(s) retrieved.");
			
			for (int i = 0; i < length; i++) {
				System.out.println(pacientes[i]);
				HashMap<String, Object> mapPacientes = new HashMap<String, Object>();
				mapPacientes.put("Rut", pacientes[i].getRut());
				mapPacientes.put("Nombre", pacientes[i].getNombre());
				mapPacientes.put("Direccion", pacientes[i].getDireccion());
				listaPaciente.add(mapPacientes);
			}
			
		} catch (PersistentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		HashMap<String, Object> map = new HashMap<String, Object>();
		
		Gson gson = new Gson();
		resultJSON = gson.toJson(listaPaciente);
		
		map.put("Contenido", resultJSON);
		Gson gson2 = new Gson();
		return gson2.toJson(map);
	}
	
	/**
	 * Este metodo obtiene la totalidad de pacientes (rut, nombre) que existen en la base de datos.
	 * @return Retorna un String con formato JSON que queda a disposicion del cliente.
	 */
	public String obtenerRutPacientes(){
		String resultJSON = "";
		HashMap<String, String> listaPaciente = new HashMap<String,String>();
		
		System.out.println("Listing Paciente...");
		DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
		Paciente[] pacientes;
		try {
			pacientes = lDAOFactory.getPacienteDAO().listPacienteByQuery(null, null);
			int length = pacientes.length;
			for (int i = 0; i < length; i++) {
				listaPaciente.put(pacientes[i].getRut().toString(), pacientes[i].getNombre());
				System.out.println(pacientes[i]);
			}
			System.out.println(length + " record(s) retrieved.");
		} catch (PersistentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		Gson gson = new Gson();
		resultJSON = gson.toJson(listaPaciente);
		return resultJSON;
	}
	
	/**
	 * Este metodo obtiene la totalidad de opciones de prestaciones (id, prestacion) que existen en la base 
	 * de datos, para este ejercicio solo piden 5 opciones de prestaciones.
	 * @return Retorna un String con formato JSON que queda a disponible para la aplicacion cliente.
	 */
	public String obtenerOpcionPrestaciones(){
		String resultJSON = "";
		HashMap<String, String> listaPrestaciones = new HashMap<String,String>();
		
		System.out.println("Listing Prestacion...");
		DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
		OpcionPrestacion[] opcionPrestaciones;
		try {
			opcionPrestaciones = lDAOFactory.getOpcionPrestacionDAO().listOpcionPrestacionByQuery(null, null);
			int length = opcionPrestaciones.length;
			for (int i = 0; i < length; i++) {
				listaPrestaciones.put(opcionPrestaciones[i].getId_opcion()+"", opcionPrestaciones[i].getOpcion().toString());
				System.out.println(opcionPrestaciones[i]);
			}
			System.out.println(length + " record(s) retrieved.");
		} catch (PersistentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		Gson gson = new Gson();
		resultJSON = gson.toJson(listaPrestaciones);
		return resultJSON;
	}
	
	public String obtenerPrestaciones(){
		String resultJSON = "";
		ArrayList<HashMap<String, Object>> listaPrestaciones = new ArrayList<HashMap<String,Object>>();

		DAOFactory lDAOFactory = DAOFactory.getDAOFactory();
		System.out.println("Listing Prestacion...");
		Prestacion[] prestaciones;
		
		
		try {
			prestaciones = lDAOFactory.getPrestacionDAO().listPrestacionByQuery(null, null);
			int length = prestaciones.length;
			System.out.println(length + " record(s) retrieved.");
			
			for (int i = 0; i < length; i++) {
				System.out.println(prestaciones[i]);
				HashMap<String, Object> mapPrestaciones = new HashMap<String, Object>();
				mapPrestaciones.put("IdPrestacion", prestaciones[i].getId_prestacion());
				mapPrestaciones.put("Diagnostico", prestaciones[i].getDiagnostico());
				mapPrestaciones.put("Fecha", prestaciones[i].getFecha());
				mapPrestaciones.put("PacienteRut", prestaciones[i].getPacienterut().getRut());
				mapPrestaciones.put("IdOpcion", prestaciones[i].getOpcionPrestacionid_opcion().getId_opcion());
				listaPrestaciones.add(mapPrestaciones);
			}
			
		} catch (PersistentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		HashMap<String, Object> map = new HashMap<String, Object>();
		
		Gson gson = new Gson();
		resultJSON = gson.toJson(listaPrestaciones);
		
		map.put("Contenido", resultJSON);
		Gson gson2 = new Gson();
		return gson2.toJson(map);
	}
}
